package ck.springboot.aop.controller;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import ck.springboot.aop.TokenResult;
import ck.springboot.aop.domain.ApiTokenInfos;
import ck.springboot.aop.domain.ApiUserInfos;
import ck.springboot.aop.mapper.ApiTokenInfosMapper;
import ck.springboot.aop.mapper.ApiUserInfosMapper;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import tk.mybatis.mapper.entity.Example;

@RestController
@RequestMapping(value = "/jwt")
public class TokenController {	

	@Autowired
	private ApiTokenInfosMapper apiTokenInfosMapper;

	@Autowired
	private ApiUserInfosMapper apiUserInfosMapper;

	/**
	 * 获取token，更新token
	 * 
	 * @param appId
	 *            用户编号
	 * @param appSecret
	 *            用户密码
	 * @return
	 */
	@RequestMapping(value = "/token", method = { RequestMethod.POST, RequestMethod.GET })
	public TokenResult token(@RequestParam String appId, @RequestParam String appSecret) {
		TokenResult token = new TokenResult();
		// appId is null
		if (appId == null || appId.trim() == "") {
			token.setFlag(false);
			token.setMsg("appId is not found!");
		}
		// appSecret is null
		else if (appSecret == null || appSecret.trim() == "") {
			token.setFlag(false);
			token.setMsg("appSecret is not found!");
		} else {
			// 根据appId查询用户实体
			Example example = new Example(ApiUserInfos.class);
			example.createCriteria().andEqualTo("auiAppId", appId);
			ApiUserInfos userDbInfo = apiUserInfosMapper.selectOneByExample(example);
			// 如果不存在
			if (userDbInfo == null) {
				token.setFlag(false);
				token.setMsg("appId : " + appId + ", is not found!");
			}
			// 验证appSecret是否存在
			else if (!new String(userDbInfo.getAuiAppSecret()).equals(appSecret.replace(" ", "+"))) {
				token.setFlag(false);
				token.setMsg("appSecret is not effective!");
			} else {
				// 检测数据库是否存在该appId的token值
				Example example2 = new Example(ApiTokenInfos.class);
				example2.createCriteria().andEqualTo("atiAppId", appId);
				ApiTokenInfos tokenDBEntity = apiTokenInfosMapper.selectOneByExample(example2);
				// 返回token值
				String tokenStr = null;
				// tokenDBEntity == null -> 生成newToken -> 保存数据库 -> 写入内存 ->
				// 返回newToken
				if (tokenDBEntity == null) {
					// 生成jwt,Token
					tokenStr = createNewToken(appId);
					// 将token保持到数据库
					tokenDBEntity = new ApiTokenInfos();
					tokenDBEntity.setAtiAppId(userDbInfo.getAuiAppId());
					tokenDBEntity.setAtiBuildTime(String.valueOf(System.currentTimeMillis()));
					tokenDBEntity.setAtiToken(tokenStr.getBytes());
					apiTokenInfosMapper.insertSelective(tokenDBEntity);
				}
				// tokenDBEntity != null -> 验证是否超时 ->
				// 不超时 -> 直接返回dbToken
				// 超时 -> 生成newToken -> 更新dbToken -> 更新内存Token -> 返回newToken
				else {
					// 判断数据库中token是否过期，如果没有过期不需要更新直接返回数据库中的token即可
					// 数据库中生成时间
					long dbBuildTime = Long.valueOf(tokenDBEntity.getAtiBuildTime());
					// 当前时间
					long currentTime = System.currentTimeMillis();
					// 如果当前时间 - 数据库中生成时间 < 7200 证明可以正常使用
					long second = TimeUnit.MILLISECONDS.toSeconds(currentTime - dbBuildTime);
					if (second > 0 && second < 7200) {
						tokenStr = new String(tokenDBEntity.getAtiToken());
					}
					// 超时
					else {
						// 生成newToken
						tokenStr = createNewToken(appId);
						// 更新token
						tokenDBEntity.setAtiToken(tokenStr.getBytes());
						// 更新生成时间
						tokenDBEntity.setAtiBuildTime(String.valueOf(System.currentTimeMillis()));
						// 执行更新
						apiTokenInfosMapper.updateByPrimaryKeySelective(tokenDBEntity);
					}
				}
				// 设置返回token
				token.setToken(tokenStr);
			}
		}
		return token;
	}

	/**
	 * 创建新token
	 * 
	 * @param appId
	 * @return
	 */
	private String createNewToken(String appId) {
		// 获取当前时间
		Date now = new Date(System.currentTimeMillis());
		// 过期时间
		Date expiration = new Date(now.getTime() + 7200000);
		return Jwts.builder().setSubject(appId)
				// .claim(YAuthConstants.Y_AUTH_ROLES, userDbInfo.getRoles())
				.setIssuedAt(now).setIssuer("Online YAuth Builder").setExpiration(expiration)
				.signWith(SignatureAlgorithm.HS256, "HengYuAuthv1.0.0").compact();
	}
}
